/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import configuration from '@system.configuration';
import prompt from '@system.prompt';
import router from '@system.router';
import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect, Level} from '@ohos/hypium';

export default function basicabilityapi() {
    describe('basicabilityapi', function () {
        let testResult;
        let testResultFail;
        let test;
        beforeAll(function () {
            testResult = true;
            testResultFail = false;
            test = "success"
        });
        beforeEach(function () {
        });
        afterEach(function () {
        });
        afterAll(function () {
        });

        async function backToIndex(){
            let backToIndexPromise = new Promise((resolve, reject) => {
                setTimeout(() => {
                    router.back({
                        uri: 'pages/index/index'
                    });
                    resolve();
                }, 1500);
            });
            let clearPromise = new Promise((resolve, reject) => {
                setTimeout(() => {
                    router.clear();
                      console.info('backIndexSuccess');
                    resolve();
                }, 1500);
            });
            await backToIndexPromise.then(() => {
                return clearPromise;
            });
        }

        /**
         * @tc.number    SUB_ACE_BASICABILITY_JS_API_0100
         * @tc.name      testClearInterval
         * @tc.desc      Cancel the repetitive timing tasks previously set by setInterval.
         */
        it('testClearInterval', Level.LEVEL0, async function(done) {
            console.info('testClearInterval START');
            let res = 0;
            let intervalID = -1;
            let promise1 = new Promise((resolve, reject) => {
                intervalID = setInterval(function () {
                    res++;
                    console.info('testClearInterval res = ' + res);
                    resolve();
                }, 100);
            });
            let promise2 = new Promise((resolve, reject) => {
                setTimeout(function () {
                    console.info('[clearInterval] start');
                    clearInterval(intervalID);
                    console.info('[clearInterval] end');
                    resolve();
                }, 600);
            });
            Promise.all([promise1, promise2]).then(() => {
                console.info('testClearInterval finally');
                expect(5).assertEqual(res);
                console.info('testClearInterval END');
                done();
            });
        });

        /**
         * @tc.number    SUB_ACE_BASICABILITY_JS_API_0200
         * @tc.name      testConsole
         * @tc.desc      Print a text message.
         */
        it('testConsole', Level.LEVEL0, function () {
            console.info('testConsole START');
            try{
                const versionCode = 1.1;
                console.info('[console.info] versionCode: ' + versionCode);
                console.debug('[console.debug] versionCode: ' + versionCode);
                console.log('[console.log] versionCode: ' + versionCode);
                console.warn('[console.warn] versionCode: ' + versionCode);
                console.error('[console.error] versionCode: ' + versionCode);
                expect(test).assertEqual('success');
                console.info('testConsole END');
            }
            catch(e){
                console.info('testConsole ERROR' + e);
            }
        });

        /**
         * @tc.number    SUB_ACE_BASICABILITY_JS_API_0300
         * @tc.name      testRouterPush
         * @tc.desc      Go to the specified page of the application.
         */
        it('testRouterPush', Level.LEVEL0, async function (done) {
            console.info('testRouterPush START');
            let options = {
                uri : 'pages/routerPush/index'
            }
            let promise1 = new Promise((resolve, reject) => {
                router.push(options);
                resolve();
            });
            let promise2 = new Promise((resolve, reject) => {
                setTimeout(() => {
                    let pages = router.getState();
                    console.info("[router.push] getState" + JSON.stringify(pages));
                    expect("pages/routerPush/").assertEqual(pages.path);
                    console.info("[router.push] getLength:" + router.getLength());
                    expect("2").assertEqual(router.getLength());
                    console.info('testRouterPush SUCCESS');
                    resolve();
                }, 500);
            });
            await promise1.then(() => {
                return promise2;
            });
            await backToIndex();
            console.info('testRouterPush END');
            console.info('testRouterPush ENDx');
            done();
        });

        /**
         * @tc.number    SUB_ACE_BASICABILITY_JS_API_0310
         * @tc.name      testRouterPushNotExist
         * @tc.desc      Test push not exist page.
         */
        it('testRouterPushNotExist', Level.LEVEL0, async function (done) {
            // console.info('testRouterPushNotExist START');
             console.info('testRouterPushNotExist START');

            let promise1 = new Promise((resolve, reject) => {
                console.info('testRouterPushNotExist 2clear');
                router.push({
                    uri: 'pages/routerNotExist/index'
                });
                resolve();
            });
            let promise2 = new Promise((resolve, reject) => {
                setTimeout(() => {
                    let pages = router.getState();
                    console.info("testRouterPushNotExist getState" + JSON.stringify(pages));
                    expect("pages/index/").assertEqual(pages.path);
                    console.info("testRouterPushNotExist getLength:" + router.getLength());
                    expect("1").assertEqual(router.getLength());
                    console.info('testRouterPushNotExist success');
                    resolve();
                }, 1500);
            });
            await promise1.then(() => {
                return promise2;
            });
            console.info('testRouterPushNotExist END');
            done();
        });

        /**
         * @tc.number    SUB_ACE_BASICABILITY_JS_API_0400
         * @tc.name      testRouterReplace
         * @tc.desc      Replace the current page with a page in the application, and destroy the replaced page.
         */
        it('testRouterReplace', Level.LEVEL0, async function (done) {
            console.info('testRouterReplace01 START');
            let options = {
                uri : 'pages/routerPush/index'
            }
            let promise1 = new Promise((resolve, reject) => {
                router.push(options);
                resolve();
            });
            let repleasePage = {
                uri : 'pages/routerReplace/index'
            }
            let promise2 = new Promise((resolve, reject) => {

                console.info("testRouterReplace 3x");
                setTimeout(() => {
                    console.info("testRouterReplace 1");
                    router.replace(repleasePage);
                    resolve();
                }, 1500);

            });
            //替换堆栈数量不会变
            let promise3 = new Promise((resolve, reject) => {
                setTimeout(() => {
                    console.info("testRouterReplace 4x");
                    let pages = router.getState();
                    console.info("[router.replace] getState" + JSON.stringify(pages));
                    expect("pages/routerReplace/").assertEqual(pages.path);
                    console.info("[router.replace] getLength:" + router.getLength());
                    expect("2").assertEqual(router.getLength());
                    console.info('testRouterReplace SUCCESS');
                    resolve();
                }, 2000);
            });
            await promise1.then(() => {
                return promise2;
            }).then(() => {
                return promise3;
            });
            await backToIndex();
            console.info('testRouterReplace END');
            done();
        });

        /**
         * @tc.number    SUB_ACE_BASICABILITY_JS_API_0410
         * @tc.name      testRouterReplaceNotExist
         * @tc.desc      Test replace not exist page.
         */
        it('testRouterReplaceNotExist', Level.LEVEL0, async function (done) {
            console.info('testRouterReplaceNotExist START');
            await setTimeout(() => {
                router.replace({
                    uri: 'pages/routerNotExist/index'
                });
            }, 2500);
            await setTimeout(() => {
                let pages = router.getState();
                console.info("testRouterReplaceNotExist getState" + JSON.stringify(pages));
                expect("pages/index/").assertEqual(pages.path);
                console.info("testRouterReplaceNotExist getLength:" + router.getLength());
                expect("1").assertEqual(router.getLength());
                console.info('testRouterReplaceNotExist END');
                done();
            }, 2000);
        });

        /**
         * @tc.number    SUB_ACE_BASICABILITY_JS_API_0500
         * @tc.name      testRouterBack
         * @tc.desc      Return to the previous page or the specified page.
         */
        it('testRouterBack', Level.LEVEL0, async function (done) {
            console.info('testRouterBack START');
            let promise1 = new Promise((resolve, reject) => {
                router.push({
                    uri: 'pages/routerPush/index'
                });
                resolve();
            });
            let promise2 = new Promise((resolve, reject) => {
                setTimeout(() => {
                    router.back({
                        uri: 'pages/index/index'
                    });
                    resolve();
                }, 2000);
            });
            let promise3 = new Promise((resolve, reject) => {
                setTimeout(() => {
                    let pages = router.getState();
                    console.info("[router.back] getState" + JSON.stringify(pages));
                    expect("pages/index/").assertEqual(pages.path);
                    console.info("[router.back] getLength:" + router.getLength());
                    expect("1").assertEqual(router.getLength());
                    console.info('testRouterBack SUCCESS');
                    resolve();
                }, 4000);
            });
            await promise1.then(() => {
                return promise2;
            }).then(() => {
                return promise3;
            });
            console.info('testRouterBack END');
            done();
        });

        /**
         * @tc.number    SUB_ACE_BASICABILITY_JS_API_0600
         * @tc.name      testRouterClear
         * @tc.desc      Clear all historical pages in the page stack, and only keep the current page as the top page.
         */
        it('testRouterClear', Level.LEVEL0, function () {
            console.info('testRouterClear START');
            router.clear();
            console.info("[router.clear] router.getLength:" + router.getLength());
            expect("1").assertEqual(router.getLength());
            console.info('testRouterClear END');
        });

        /**
         * @tc.number    SUB_ACE_BASICABILITY_JS_API_0700
         * @tc.name      testRouterLength
         * @tc.desc      Get the number of pages currently in the page stack.
         */
        it('testRouterLength', Level.LEVEL0, async function (done) {
            console.info('testRouterLength START');
            let size = router.getLength();
            console.info('[router.getLength] pages stack size = ' + size);
            expect(size).assertEqual('1');
            let options = {
                uri : 'pages/routerPush/index'
            }
            let promise1 = new Promise((resolve, reject) => {
                router.push(options);
                resolve();
            });
            let promise2 = new Promise((resolve, reject) => {
                setTimeout(() => {
                    console.info("testRouterLength getLength:" + router.getLength());
                    expect("2").assertEqual(router.getLength());
                    console.info('testRouterLength SUCCESS');
                    resolve();
                }, 500);
            });
            await promise1.then(() => {
                return promise2;
            });
            await backToIndex();
            console.info('testRouterLength END');
            done();
        });

        /**
         * @tc.number    SUB_ACE_BASICABILITY_JS_API_0800
         * @tc.name      testRouterGetState
         * @tc.desc      Get the status information of the current page.
         */
        it('testRouterGetState', Level.LEVEL0, async function (done) {
            console.info('[jyl] testRouterGetState START');
            await setTimeout(() => {
                let page = router.getState();
                console.info('[router.getState] index: ' + page.index);
                console.info('[router.getState] name: ' + page.name);
                console.info('[router.getState] path: ' + page.path);
                expect(page.index).assertEqual(1);
                expect(page.name).assertEqual('index');
                expect(page.path).assertEqual('pages/index/');
                console.info('testRouterGetState END');
                done();
            }, 2000);
        });

        /**
         * @tc.number    SUB_ACE_BASICABILITY_JS_API_0900
         * @tc.name      testPromptShowToast
         * @tc.desc      Show text pop-up window.
         */
        it('testPromptShowToast', Level.LEVEL0, function () {
            try{
                console.info('testPromptShowToast START');
                const delay = 5000;
                prompt.showToast({
                    message: 'message',
                    duration: delay,
                });
                expect(test).assertEqual('success');
                console.info('[prompt.showToast] success');
                console.info('testPromptShowToast END');
            }
            catch(e){
                console.log('testPromptShowToast ERROR' + e);
            }
        });

        /**
         * @tc.number    SUB_ACE_BASICABILITY_JS_API_1000
         * @tc.name      testPromptDialog
         * @tc.desc      Display the dialog box in the page.
         */
        it('testPromptDialog', Level.LEVEL0, function () {
            console.info('testPromptDialog START')
            try{
                prompt.showDialog({
                    title: 'dialog showDialog test',
                    message: 'message of dialog',
                    buttons: [
                        {
                            text: 'OK',
                            color: '#0000ff',
                            index: 0
                        }
                    ],
                    success: function (ret) {
                        console.info("[prompt.showDialog] ret.index " + ret.index);
                        expect(testResult).toBeTrue();
                    },
                    cancel: function () {
                        console.log('[prompt.showDialog] dialog cancel callback');
                        expect(testResultFail).toBeTrue();
                    },
                    complete: function () {
                        console.log('[prompt.showDialog] complete');
                    }
                });
                console.info('testPromptDialog END');
            }
            catch(e) {
                console.info('testPromptDialog error ' + e);
            }
        });

        /**
         * @tc.number    SUB_ACE_BASICABILITY_JS_API_1100
         * @tc.name      testConfigurationGetLocale
         * @tc.desc      Get the current language and region of the app. Synchronize with the language and region.
         */
        it('testConfigurationGetLocale', Level.LEVEL0, function () {
            console.info('testConfigurationGetLocale START');
            const localeInfo = configuration.getLocale();
            console.info("[configuration.getLocale] localeInfo: " + JSON.stringify(localeInfo));
            console.info("[configuration.getLocale] language: " + localeInfo.language);
            console.info("[configuration.getLocale] countryOrRegion: " + localeInfo.countryOrRegion);
            console.info("[configuration.getLocale] dir: " + localeInfo.dir);
            expect(localeInfo.language).assertEqual('zh');
            expect(localeInfo.dir).assertEqual('ltr');
            console.info('testConfigurationGetLocale END');
        });

        /**
         * @tc.number    SUB_ACE_BASICABILITY_JS_API_1200
         * @tc.name      testSetTimeout
         * @tc.desc      Set up a timer that executes a function or a specified piece of code after the timer expires.
         */
        it('testSetTimeout', Level.LEVEL0, async function (done) {
            console.info('testSetTimeout START');
            let startTime = new Date().getTime();
            const delay = 200;
            await setTimeout(function (v1, v2) {
                let endTime = new Date().getTime();
                console.info("[setTimeout] startTime: " + startTime);
                console.info("[setTimeout] endTime: " + endTime);
                console.info('[setTimeout] delay: ' + (endTime - startTime));
                console.info('[setTimeout] v1: ' + v1);
                console.info('[setTimeout] v2: ' + v2);
                expect('test').assertEqual(v1);
                expect('message').assertEqual(v2);
                expect(endTime - startTime >= delay).assertTrue();
                console.info('testSetTimeout END');
                done();
            }, delay, 'test', 'message');
        });

        /**
         * @tc.number    SUB_ACE_BASICABILITY_JS_API_1300
         * @tc.name      testClearTimeout
         * @tc.desc      The timer previously established by calling setTimeout() is cancelled.
         */
        it('testClearTimeout', Level.LEVEL0, async function (done) {
            console.info('testClearTimeout START');
            let res = 0;
            let timeoutID = setTimeout(function () {
                res++;
            }, 700);
            await setTimeout(function () {
                console.info('testClearTimeout delay 0.5s')
                clearTimeout(timeoutID);
                console.info("[clearTimeout] success");
            }, 500);
            await setTimeout(function () {
                expect(0).assertEqual(res);
                console.info('testClearTimeout END');
                done();
            }, 1000);
        });

        /**
         * @tc.number    SUB_ACE_BASICABILITY_JS_API_1400
         * @tc.name      testSetInterval
         * @tc.desc      Call a function or execute a code segment repeatedly, with a fixed time delay between each call.
         */
        it('testSetInterval', Level.LEVEL0, async function (done) {
            console.info('testSetInterval START');
            let res = 0;
            let intervalID = setInterval(function () {
                res++;
            }, 100);
            await setTimeout(function () {
                expect(9).assertEqual(res);
                console.info('testSetInterval SUCCESS');
                clearInterval(intervalID);
                console.info('testSetInterval END');
                done();
            }, 1000);
        });


        /**
         * @tc.number    SUB_ACE_BASICABILITY_JS_API_1500
         * @tc.name      testRequestAnimationFrame
         * @tc.desc      Sets a vsync after which a function will be executed.
         */
        it('testRequestAnimationFrame', Level.LEVEL0, async function (done) {
            console.info('testRequestAnimationFrame START');
            let requestId = requestAnimationFrame(function () {
                console.info('testRequestAnimationFrame success');
                expect(true).assertTrue();
                done();
            });
        });

        /**
         * @tc.number    SUB_ACE_BASICABILITY_JS_API_1600
         * @tc.name      testCancelAnimationFrame
         * @tc.desc      Indicates the vsync callback ID returned by "requestAnimationFrame()".
         */
        it('testCancelAnimationFrame', Level.LEVEL0, async function (done) {
            console.info('testCancelAnimationFrame START');
            let result = true;
            let requestId = requestAnimationFrame(function () {
                console.info('testCancelAnimationFrame fail');
                result = false;
            });
            cancelAnimationFrame(requestId);
            await setTimeout(function () {
                expect(result).assertTrue();
                done();
            }, 1000);
        });
    });
}
